import React from 'react';
import classNames from 'classnames';
import Icon from '../Icon';
import Select from '../Select';
import Input from '../Input';

import './Pagination.less';

/**
 * PagePrev Component
 */
// eslint-disable-next-line react/display-name
const PagePrev = (props) => {
    const className = classNames('cm-pagination-num cm-pagination-prev', {
        'cm-pagination-num-disabled': props.current === 1
    });
    return (<li onClick={props.onClick} className={className}>
        <Icon name='chevron-left' size={14}/>
    </li>); 
};

/**
 * PageNext Component
 */
// eslint-disable-next-line react/display-name
const PageNext = (props) => {   
    const className = classNames('cm-pagination-num cm-pagination-next', {
        'cm-pagination-num-disabled': props.disabled
    });

    return (<li onClick={props.onClick} className={className}>
        <Icon name='chevron-right' size={14}/>
    </li>);
};

// eslint-disable-next-line react/display-name
const PageItem = (props) => {
    const className = classNames('cm-pagination-num', {
        'cm-pagination-item-active': props.active
    });
    return (<li onClick={props.onClick} className={className}>
        {props.currentIndex}
    </li>);
};

export default class Pagination extends React.Component {
    displayName = 'Pagination';

    static defaultProps = {
        total: 0,
        pageSize: 10,
        pageNum: 1,
        showMinNums: 3,
        displayedPages: 5
    };

    state = {
        _current: this.props.current || 1     
    }

    prev () {
        if (this.props.current > 1) {
            this._handleChange(this.props.current - 1);
        }
    }

    next () {
        if (this.props.current < this._calcPage()) {
            this._handleChange(this.props.current + 1);
        }
    }

    _calcPage () {
        const {pageSize, total} = this.props;
        // 没数据的时候默认为第一页
        if (total === 0) {
            return 1;
        }
        return Math.floor((total - 1) / pageSize) + 1;
    }

    
    /**
     * 获取中间显示的页号
     * @method _getInterval
     * @returns {{start: number, end: number}}
     * @private
     */
    _getInterval () {
        const {displayedPages, current} = this.props;
        const pages = this._calcPage();
        const half = displayedPages / 2;
        return {
            start: Math.ceil(current > half
                ? Math.max(Math.min(current - half, (pages - displayedPages)), 0)
                : 0),
            end: Math.ceil(current > half ? Math.min(current + half, pages) : Math.min(half, pages))
        };
    }

    _isValid (page) {
        return typeof page === 'number' && page >= 1;
    }

    /**
     * 页号改变
     * @method _handleChange
     * @param p 当前页号
     * @returns {*}
     * @private
     */
    _handleChange (p) {
        let page = p;
        const {current, pageSize} = this.props;
        if (this._isValid(page) && page !== current) {
            if (page > this._calcPage()) {
                page = this._calcPage();
            }

            this.setState({
                _current: page
            });

            if (this.props.onChange) {
                this.props.onChange(page, pageSize);
            }
        }
    }

    rednderItems () {
        const {current} = this.props;
        const pages = this._calcPage();
        const pagerList = [];
        const interval = this._getInterval();
        if (pages <= 9) {
            for (let i = 0; i < pages; i++) {
                const active = current === i + 1;
                pagerList.push((<PageItem key={i + 1} onClick={this._handleChange.bind(this, i + 1)}
                    active={active} currentIndex={i + 1} />));
            }
        } else {
            const edges = 2;
            const end = Math.min(edges, interval.start);
            for (let i = 0; i < end; i++) {
                pagerList.push(<PageItem key={i + 1} onClick={this._handleChange.bind(this, i + 1)}
                    currentIndex={i + 1} />);
            }
            if (edges < interval.start && (interval.start - edges !== 1)) {
                pagerList.push(<li key={'...1'} className='cm-pagination-num cm-pagination-ellipse'><span className='ellipse'>•••</span></li>);
            } else if (interval.start - edges === 1) {
                pagerList.push(<PageItem key={edges + 1} onClick={this._handleChange.bind(this, edges + 1)}
                    currentIndex={edges + 1} />);
            }

            for (let j = interval.start; j < interval.end; j++) {
                const active = current === j + 1;
                pagerList.push(<PageItem key={j + 1} onClick={this._handleChange.bind(this, j + 1)}
                    currentIndex={j + 1} active={active} />);
            }

            if (interval.end < pages && edges > 0) {
                if (pages - edges > interval.end && (pages - edges - interval.end !== 1)) {
                    pagerList.push(<li key={'...2'} className='cm-pagination-num cm-pagination-ellipse'><span className='ellipse'>•••</span></li>);
                } else if (pages - edges - interval.end === 1) {
                    pagerList.push(<PageItem key={interval.end + 1}
                        onClick={this._handleChange.bind(this, interval.end + 1)}
                        currentIndex={interval.end + 1} />);
                }
                const begin = Math.max(pages - edges, interval.end);
                for (let k = begin; k < pages; k++) {
                    pagerList.push(<PageItem key={k + 1} onClick={this._handleChange.bind(this, k + 1)}
                        currentIndex={k + 1} />);
                }
            }
        }
        return pagerList;
    }

    onChangePageSize = (v) => {
        if (this.props.onChangePageSize) {
            this.props.onChangePageSize(v);
        }
    }

    gotoPage = (v) => {
        this._handleChange(parseInt(v));
        this.setState({
            _current: v
        });
    }

    static  getDerivedStateFromProps (nextProps, prevState) {
        if (nextProps.current !== prevState._current) {
            return {_current: nextProps.current};
        }
        return null;
    }

    render () {
        const {className, style, theme, shape, current, size, total, showTotal, 
            showSizer, showJumper, pageSize} = this.props;
        const clazzName = classNames('cm-pagination', className, {
            [`cm-pagination-${theme}`]: theme,
            [`cm-pagination-${shape}`]: shape,
            [`cm-pagination-${size}`]: size
        });
        return <div className={clazzName} style={style}>
            {
                showTotal
                    ? <span className='cm-pagination-text mr-5'>共{total}条</span>
                    : null
            }
            <ul className='cm-pagination-num-list'>
                <PagePrev current={current} onClick={this.prev.bind(this, null)} />
                {this.rednderItems()}
                <PageNext current={current} onClick={this.next.bind(this, null)} disabled={current === this._calcPage()} />
            </ul>
            {
                showSizer
                    ? <span className='cm-pagination-sizer'>
                        <Select value={`${pageSize}`} size={size}
                            onChange={this.onChangePageSize.bind(this)}
                            data={[
                                {id: '10', text: '10条/页'},
                                {id: '20', text: '20条/页'},
                                {id: '30', text: '30条/页'},
                                {id: '40', text: '40条/页'},
                                {id: '50', text: '50条/页'}
                            ]}/>
                    </span>
                    : null
            }
            {
                showJumper
                    ? <span className='cm-pagination-jumper ml-5'>
                        <span className='cm-pagination-text mr-5'>跳至</span>
                        <Input style={{width: size === 'small' ? 40 : 60}} className='mr-5' 
                            value={this.state._current} 
                            size={size} onChange={this.gotoPage}/>
                        <span className='cm-pagination-text'>页</span>
                    </span>
                    : null
            }
        </div>;
    }
}
